package stardust.product.xspider;


import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import stardust.core.log.Log;
import stardust.core.network.protocol.http.HttpRequestMeta;
import stardust.core.network.protocol.http.HttpResponseMeta;
import stardust.core.network.protocol.http.support.URL;
import stardust.core.support.db.DataAccessObject;
import stardust.core.support.db.StardustDB;


public abstract class AbstractXSpiderCallback implements XSpiderCallback
{
  
  public static final Log log = new Log(AbstractXSpiderCallback.class);
  
  private String website;
  private String websiteKeyword;
  
  private LinkedList<XSpiderURL> cache = new LinkedList<XSpiderURL>();
  
  public AbstractXSpiderCallback(String website, String websiteKeyword)
  {
    this.website = website;
    this.websiteKeyword = websiteKeyword;
  }

  public void saveURL(XSpiderURL from, List<String> url)
  {
    DataAccessObject dao = StardustDB.getDataAccessObject();
    int count = 0;
    URL u;
    
    try
    {
      for (String s : url)
      {
        if (this.websiteKeyword != null && s.indexOf(this.websiteKeyword) == -1)
        {
          continue;
        }
        
        try
        {
          u = new URL(s);
        }
        catch (Exception e)
        {
          //log.warning(e, "记录链接失败 -> " + s);
          continue;
        }
        
        if (dao.get("SELECT * FROM TB_SD_XSPIDER WHERE XS_URL = ?", s) == null)
        {
          count++;
          dao.execute
          (
              "INSERT INTO TB_SD_XSPIDER VALUES (NULL, NOW(), NULL, ?, ?, '0', ?, NULL, NULL, NULL, NULL, NULL, NULL);",
              s, from.getUrl(), u.getHost() + ":" + u.getPort()
          );
          dao.execute("COMMIT");
        }
      }
    }
    finally
    {
      log.debug("\t新增链接 -> " + count + "个");
      dao.close(true);
    }
  }
  
  public void resolve(XSpiderURL url, HttpRequestMeta reqMeta, HttpResponseMeta rspMeta, String encode, String title, String html)
  {
    log.debug("\t解析文档 ->\t" + (rspMeta != null ? rspMeta.getStatusCode() : "ERR") + "\t" + ((rspMeta.getOthers().containsKey("Content-Length") ? Integer.parseInt(rspMeta.getOthers().get("Content-Length")) : rspMeta.getData().length) / 1024) + "KB\t" + url.getUrl());
    
    DataAccessObject dao = StardustDB.getDataAccessObject();
    
    try
    {
      if (rspMeta == null)
      {
        dao.execute
        (
            "UPDATE TB_SD_XSPIDER SET XS_MODIFY_TIME = NOW(), XS_FETCH_FLAG = 3, XS_REQUEST = ?, XS_RESPONSE = ?, XS_STATUS_CODE = ?, XS_SIZE = ? WHERE XS_URL = ?",
            reqMeta.getRequest(), null, null, 0, url.getUrl()
        );
      }
      else
      {
        dao.execute
        (
            "UPDATE TB_SD_XSPIDER SET XS_MODIFY_TIME = NOW(), XS_FETCH_FLAG = 2, XS_REQUEST = ?, XS_RESPONSE = ?, XS_STATUS_CODE = ?, XS_SIZE = ?, XS_TITLE = ? WHERE XS_URL = ?",
            reqMeta.getRequest(), rspMeta.getResponse(), rspMeta.getStatusCode(), rspMeta.getOthers().containsKey("Content-Length") ? rspMeta.getOthers().get("Content-Length") : rspMeta.getData().length, title, url.getUrl()
        );
      }
      
      dao.execute("COMMIT");
    }
    finally
    {
      dao.close(true);
    }
  }
  
  public synchronized XSpiderURL nextURL()
  {
    if (!this.cache.isEmpty())
    {
      return this.cache.removeFirst();
    }
    
    DataAccessObject dao = StardustDB.getDataAccessObject();

    try
    {
      List<Map<String, Object>> u = dao.query("SELECT * FROM TB_SD_XSPIDER WHERE XS_FETCH_FLAG = 0" + (this.website == null ? "" : " AND XS_WEBSITE = '" + this.website + "'") + " LIMIT 0, 2000");
      
      if (u != null && !u.isEmpty())
      {
        for (Map<String, Object> i : u)
        {
          XSpiderURL url = new XSpiderURL();
          
          url.setUrl((String) i.get("XS_URL"));
          url.setReferer((String) i.get("XS_REFERER"));
          
          this.cache.add(url);
          
          dao.execute("UPDATE TB_SD_XSPIDER SET XS_MODIFY_TIME = NOW(), XS_FETCH_FLAG = 1 WHERE XS_ID = ?", i.get("XS_ID"));
          dao.execute("COMMIT");
        }
        
        return this.nextURL();
      }
      
      return null;
    }
    finally
    {
      dao.close(true);
    }
  }

  public void onError(XSpiderURL url, Throwable e)
  {
    DataAccessObject dao = StardustDB.getDataAccessObject();
    
    try
    {
      dao.execute("UPDATE TB_SD_XSPIDER SET XS_MODIFY_TIME = NOW(), XS_FETCH_FLAG = 0, EXTRA_FLAG = ? WHERE XS_URL = ?", e.toString(), url.getUrl());
      dao.execute("COMMIT");
    }
    finally
    {
      dao.close(true);
    }
  }
  
}
